
#include "Cortisol.h"

#include <stdio.h>
#include <io.h>
#include <windows.h>
#include <fcntl.h>

#include "WGL\wgl.h"

void help() {

	cout << "Cortisol: a stress test utility for avlib builds" << endl;
	cout << "  usage: cortisol [options] --vids=path/to/videofiles" << endl;
	cout << "   options:" << endl;
	cout << "    --help : show this message and quit" << endl;
	cout << "    --vids=path : directory containing test videos" << endl;
	cout << "    --threads=n : number of decode threads" << endl;

	exit(0);
}

HANDLE       VideoRAW::statsMutex;
unsigned int VideoRAW::totalFramesDecoded = 0;
unsigned int VideoRAW::totalVideosDecoded = 0;
signed   int VideoRAW::inProgress = 0;

AVCodecLib*  AVLib::avcodec		= NULL;
AVFormatLib* AVLib::avformat	= NULL;
AVUtilLib*   AVLib::avutil		= NULL;
SWScaleLib*  AVLib::swscale		= NULL;

static int av_lock_manager_cb( void **mutex, enum AVLockOp lockOp) {

	switch(lockOp) {

	case AV_LOCK_CREATE:

		*mutex = (void*)CreateMutex(NULL,false,NULL);
		break;

	case AV_LOCK_DESTROY:

		CloseHandle((HANDLE)*mutex);
		*mutex = NULL;
		break;

	case AV_LOCK_OBTAIN:

		WaitForSingleObject((HANDLE)*mutex, INFINITE);
		break;

	case AV_LOCK_RELEASE:

		ReleaseMutex((HANDLE)*mutex);
		break;

	}

	return 0;
}

void OpenConsole()
{
	int hCrt = -1;
	FILE *hf = NULL;
	int i = -1;

	AllocConsole();

	hCrt = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
	hf = _fdopen(hCrt, "w");
	*stdout = *hf;
	setvbuf(stdout, NULL, _IONBF, 0);

	hCrt = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT);
	hf = _fdopen(hCrt, "r");
	*stdin = *hf;
	setvbuf(stdin, NULL, _IONBF, 0);

	hCrt = _open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT);
	hf = _fdopen(hCrt, "w");
	*stderr = *hf;
	setvbuf(stderr, NULL, _IONBF, 0);
}


int main(int argc, const char* argv[])  {

	try {

		WGLWindow::StaticInitialise();

		WGLWindow window0(L"first",0,800,600,false,NULL);
//		WGLWindow window1(L"second",1,800,600,false,NULL);

		const Args args(argc, argv);
		const Settings settings(args);
	
		if(settings.ShowHelpAndQuit())
			help();

		srand( (unsigned int)time(NULL) );

		AVLib::Format()->av_register_all();

		AVLib::Codec()->av_lockmgr_register( &av_lock_manager_cb );

		VideoRAW::statsMutex = CreateMutex(NULL,false,NULL);

		WorkLoad workLoad( settings );

		ThreadPool *threadPool = new ThreadPool( settings, &workLoad );

		StatusThread * statusThread = new StatusThread();

		do {

			window0.Update();

		} while( window0.ShouldClose() == false );

		delete threadPool;
		delete statusThread;

		CloseHandle(VideoRAW::statsMutex);
		AVLib::Codec()->av_lockmgr_register( NULL );

		WGLWindow::StaticDispose();

		return 0;
	}
	catch( const Exception &ex ) {

		cout << endl << endl << "EXCEPTION: " << ex.what() << endl;

		getchar();

		return -1;
	}
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow)
{
	const char *params[] = {"cortisol.exe"};

	OpenConsole();

	return main(1,params);

	FreeConsole();
}

